/********************************** (C) COPYRIGHT *******************************
* File Name          : 13ST84GINK.c
* Author             : 风一样的流逝
* Version            : V1.0
* Date               : 2023/10/25
* Description        : ESP32-C3   模拟SPI
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<unistd.h>
#include"configuration.h"
#include "freertos/FreeRTOS.h"
#include "freertos/portmacro.h"
#include "freertos/task.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "13ST84GINK.h"
spi_device_handle_t spi;//spi设备句柄 
static const char *TAG = "13-ST-84GINK";

/* 用于8位数据/命令传输 */
void VFDWriteData(unsigned char dat)
{
	unsigned char mask;

	for (mask = 0x01; mask != 0; mask <<= 1)
	{
		gpio_set_level(PIN_NUM_SCLK,0);
		if (mask & dat)
			gpio_set_level(PIN_NUM_MOSI,1);
		else
			gpio_set_level(PIN_NUM_MOSI,0);
		usleep(1);
		gpio_set_level(PIN_NUM_SCLK,1);
		usleep(1);
	}
	usleep(1);
}
/* VFD电源控制 */
void VFDPowerCtrl(unsigned char set)
{
	if(set == 1)
    {
        gpio_set_level(PIN_NUM_EFEN_EN,1);//打开灯丝电源
        vTaskDelay(200 / portTICK_PERIOD_MS);//等待电压稳定
        gpio_set_level(PIN_NUM_HDCDC_EN,1);//打开高压升压
        vTaskDelay(50 / portTICK_PERIOD_MS);//等待电压稳定
    }
    else if(set == 0)
    {
        gpio_set_level(PIN_NUM_HDCDC_EN,0);//关闭高压升压
        vTaskDelay(10 / portTICK_PERIOD_MS);//等待电压稳定
        gpio_set_level(PIN_NUM_EFEN_EN,0);//关闭灯丝电源
        vTaskDelay(10 / portTICK_PERIOD_MS);//等待电压稳定
    }
}
/* 亮度设置 */
void SetLuminance(unsigned char lum)
{
	gpio_set_level(PIN_NUM_CS,0);//开始传输
	usleep(1);
	VFDWriteData(0xe4);
	VFDWriteData(lum);//亮度设置
	gpio_set_level(PIN_NUM_CS,1);//停止传输
	usleep(1);
}
/* 用于开/关 当前屏幕显示 0关  1开 */
void VFDDisplaySwitch(unsigned char set)
{
	gpio_set_level(PIN_NUM_CS,0);//开始传输
	usleep(1);
	if (set == 1)
	{
		VFDWriteData(0xe8);//打开显示 指令
	}
	else if (set == 0)
	{
		VFDWriteData(0xea);//关闭显示 指令
	}
	gpio_set_level(PIN_NUM_CS,1);//停止传输
	usleep(1);
}
/* 待机设置  0正常模式  1待机 */
void VFDDStandby(unsigned char set)
{
	gpio_set_level(PIN_NUM_CS,0);//开始传输
	usleep(1);
	if (set == 1)
	{
		VFDWriteData(0xed);//进入待机 指令
	}
	else if (set == 0)
	{
		VFDWriteData(0xec);//正常模式 指令
	}
	gpio_set_level(PIN_NUM_CS,1);//停止传输
	usleep(1);
}
/* VFD初始化**/
void VFDInit(unsigned char slum)
{	
    gpio_config_t iocfg;

	//初始化VFD屏用到的GPIO
    iocfg.intr_type = GPIO_INTR_DISABLE;
    iocfg.mode = GPIO_MODE_OUTPUT;
    iocfg.pin_bit_mask = (1ULL<<PIN_NUM_EFEN_EN | 1ULL<<PIN_NUM_HDCDC_EN | 1ULL<<PIN_NUM_REST | 1ULL<<PIN_NUM_CS  | 1ULL<<PIN_NUM_MOSI  | 1ULL<<PIN_NUM_SCLK);
    iocfg.pull_down_en = 0;
    iocfg.pull_up_en = 1;
    gpio_config(&iocfg);

    //打开电源 并开始初始化VFD屏
	VFDPowerCtrl(1);//打开VFD电源
    ESP_LOGI(TAG, "VFD power on.");
    //spi_initialize();//初始化SPI
    ESP_LOGI(TAG, "SPI init complete.");
	gpio_set_level(PIN_NUM_REST,0);//拉低REST  再拉高重启VFD内置控制芯片
	usleep(20);
	gpio_set_level(PIN_NUM_REST,1);
	vTaskDelay(10 / portTICK_PERIOD_MS);//等待VFD内置控制芯片重启好

	gpio_set_level(PIN_NUM_CS,0);//开始传输
	usleep(1);
	VFDWriteData(0xe0); //显示设置
	VFDWriteData(0x0c);//设置显示G1~G13
	gpio_set_level(PIN_NUM_CS,1);//停止传输
	usleep(1);

	//显示模式设置
	gpio_set_level(PIN_NUM_CS,0);//开始传输
	usleep(1);
	VFDWriteData(0x00); //
	VFDWriteData(0x00);//
	gpio_set_level(PIN_NUM_CS,1);//停止传输
	usleep(1);

	//设置亮度并
	SetLuminance(slum);
}
/* 写CGRAM */
void WriteCGRAM(unsigned char x, char(*arr)[5], unsigned char n)
{
	gpio_set_level(PIN_NUM_CS,0);//CS拉低
	usleep(1);
	VFDWriteData(0x40 + x);//地址寄存器起始位置	
	VFDWriteData(arr[n][0]);
	VFDWriteData(arr[n][1]);
	VFDWriteData(arr[n][2]);
	VFDWriteData(arr[n][3]);
	VFDWriteData(arr[n][4]);
	gpio_set_level(PIN_NUM_CS,1);//CS拉高
	usleep(1);
}
/* 写入显示指令 */
void WriteDisplayCMD()
{
    gpio_set_level(PIN_NUM_CS,0);//开始传输
	usleep(1);
	VFDWriteData(0xe8);//显示写入内容
	gpio_set_level(PIN_NUM_CS,1);//停止传输
	usleep(1);
}
/* 写入一位自定义CGRAM字符待显示 */
void VFDWriteOneDIYChar(unsigned char x, unsigned char chr)
{
	gpio_set_level(PIN_NUM_CS,0);//开始传输
	usleep(1);
	VFDWriteData(0x20 + x);//地址寄存器起始位置
	VFDWriteData(chr);
	gpio_set_level(PIN_NUM_CS,1);//停止传输
	usleep(1);
}
/* 写入并显示一位自定义CGRAM字符 */
void VFDWriteOneDIYCharAndShow(unsigned char x, unsigned char chr)
{
	gpio_set_level(PIN_NUM_CS,0);//开始传输
	usleep(1);
	VFDWriteData(0x20 + x);//地址寄存器起始位置
	VFDWriteData(chr);
	gpio_set_level(PIN_NUM_CS,1);//停止传输
	usleep(1);

	WriteDisplayCMD();//显示写入内容
}
/* 写入字符串 */
void VFDWriteStr(unsigned char x, char* str)
{
	gpio_set_level(PIN_NUM_CS,0);//开始传输
	usleep(1);
	VFDWriteData(0x20 + x);//地址寄存器起始位置	 
	while (*str)
	{
		VFDWriteData(*str); //ascii与对应字符表转换  
		str++;
	}
	gpio_set_level(PIN_NUM_CS,1);//停止传输
	usleep(1);
}
/* 写入字符串并显示 */
void VFDWriteStrAndShow(unsigned char x, char* str)
{
	gpio_set_level(PIN_NUM_CS,0);//开始传输
	usleep(1);
	VFDWriteData(0x20 + x);//地址寄存器起始位置	
	while (*str)
	{
		VFDWriteData(*str); //ascii与对应字符表转换  
		str++;
	}
	gpio_set_level(PIN_NUM_CS,1);//停止传输
	usleep(1);

	WriteDisplayCMD();//显示写入内容
}
/* 写一个ADRAM并显示 */
void VFDWriteOneADRAMAndShow(unsigned char x, unsigned char dat)
{
	gpio_set_level(PIN_NUM_CS,0);//开始传输
	usleep(1);
	VFDWriteData(0x60 + x);//地址寄存器起始位置
	VFDWriteData(dat); //ascii与对应字符表转换 
	gpio_set_level(PIN_NUM_CS,1);//停止传输
	usleep(1);

	WriteDisplayCMD();//显示写入内容
}
/* 写ADRAM并显示 */
void VFDWriteAllADRAMAndShow(unsigned char* dat)
{
	gpio_set_level(PIN_NUM_CS,0);//开始传输
	usleep(1);
	VFDWriteData(0x60 + 0);//地址寄存器起始位置
	while (*dat)
	{
		VFDWriteData(*dat); //ascii与对应字符表转换 
		dat++;
	}
	gpio_set_level(PIN_NUM_CS,1);//停止传输
	usleep(1);

	WriteDisplayCMD();//显示写入内容
}